<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Connection\AsyncTcpConnection;
use Channel\Client;

require 'vendor/autoload.php';

class Proxy extends Worker {

    private $mapping = [
        3306 => 3336,
    ];

    private $asyncConn = [];


    public function __construct($socket_name = '', array $context_option = array())
    {
        parent::__construct($socket_name, $context_option);

        $this->onWorkerStart = function (){
            $this->parserIni();
            $this->onClientStart();
        };
    }


    protected function parserIni(){
        $arr = new IniParser('proxy.ini');
        $this->mapping = $arr->parse();
    }

    protected function onClientStart(){
        Client::$onConnect = function (){
            // 注册
            foreach ($this->mapping as $name => $opt){
                if ($name == 'common') {
                    continue;
                }

                Client::publish('register', [
                    'type' => $opt->type?:'tcp',
                    'port' => $opt->remote_port,
                    'identity' => $name,
                ]);
                Client::on($name, function ($event_data) use($name){
                    // connect
                    $method = $event_data['method'];
                    $this->$method($name, $event_data);
                });
            }
        };
        Client::$onClose = function (){
            Client::clearTimer();
            sleep(3);
            $this->onClientStart();
        };
        Client::connect(
            $this->mapping->common->master,
            $this->mapping->common->port
        );
    }

    protected function connect($name, $event_data){
        $conn_info = sprintf("%s://%s:%d",
            $this->mapping[$name]->type?:'tcp', $this->mapping[$name]->local_ip?:'127.0.0.1', $this->mapping[$name]->local_port
        );
        $conn = new AsyncTcpConnection($conn_info);
        // 为其绑定事件
        $conn->onMessage = function (TcpConnection $guest, $recv_bytes) use ($event_data, $name){
            // 把信息广播出去
            Client::publish('send', [
                'conn_id' => $event_data['conn_id'],
                'message' => $recv_bytes,
                'method' => 'send',
                'identity' => $name,
            ]);
        };

        $conn->onClose = function (TcpConnection $connection) use ($event_data, $name){
            Client::publish('close', [
                'conn_id' => $event_data['conn_id'],
                'method' => 'close',
                'identity' => $name
            ]);
        };
        $conn->connect();
        $this->asyncConn[$name] = $conn;
    }

    protected function send($name, $event_data){
        if (!isset($this->asyncConn[$name])) {
            return false ;
        }
        #var_dump($event_data['message']);
        $this->asyncConn[$name]->send($event_data['message']);
        return true;
    }

    protected function close($name, $message){
        if (!isset($this->asyncConn[$name])) {
            return false ;
        }
        $this->asyncConn[$name]->close();
        return true;
    }

}

new Proxy();
Worker::runAll();